package com.xw.unification.dto;

import com.xw.unification.interfaces.ResultCodeEnumerable;
import com.xw.unification.interfaces.UnifiedExceptionResolvable;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;

/**
 * 统一响应体
 *
 * @author qiwei
 * @date 2023-8-9 21:00:00
 * @since v1.0.0
 */
@Getter
@ToString
public class ResultDTO<V> implements Serializable {

    private static final long serialVersionUID = 3001253196531924621L;

    private Integer code;

    @Setter
    private String message;

    private V data;

    protected ResultDTO(ResultCodeEnumerable codeResolvable, V data) {
        if (codeResolvable == null) {
            throw new IllegalArgumentException("ResultCodeResolvable can not be null");
        }
        this.code = codeResolvable.getCode();
        this.message = codeResolvable.getMessage();
        this.data = data;
    }

    protected ResultDTO(UnifiedExceptionResolvable exceptionResolvable) {
        if (exceptionResolvable == null) {
            throw new IllegalArgumentException("UnifiedExceptionResolvable can not be null");
        }
        this.code = exceptionResolvable.getErrorCode();
        this.message = exceptionResolvable.getErrorMessage();
        this.data = (V) exceptionResolvable.getBody();
    }

    protected ResultDTO(int code, String message, V data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <V> ResultDTO<V> result(ResultCodeEnumerable codeResolvable, V data) {
        if (codeResolvable == null) {
            throw new IllegalArgumentException("ResultCodeResolvable can not be null");
        }
        if (!(codeResolvable instanceof Enum)) {
            throw new IllegalArgumentException("ResultCodeResolvable must be enum instance");
        }
        return new ResultDTO<>(codeResolvable, data);
    }

    public static <V> ResultDTO<V> ok(V data) {
        int errorCode = ResultCodeEnumerable.DEFAULT.getSuccessCode();
        String errorMsg = ResultCodeEnumerable.DEFAULT.getSuccessMsg();
        return new ResultDTO<>(errorCode, errorMsg, data);
    }

    public static <V> ResultDTO<V> error(ResultCodeEnumerable codeResolvable, V data) {
        if (codeResolvable == null) {
            throw new IllegalArgumentException("ResultCodeResolvable can not be null");
        }
        if (!(codeResolvable instanceof Enum)) {
            throw new IllegalArgumentException("ResultCodeResolvable must be enum instance");
        }
        if (codeResolvable.getCode() == ResultCodeEnumerable.DEFAULT.getSuccessCode()) {
            throw new IllegalArgumentException("ResultCodeResolvable must be enum instance of fail-code");
        }
        return new ResultDTO<>(codeResolvable, data);
    }

    public static <V> ResultDTO<V> error(UnifiedExceptionResolvable exceptionResolvable) {
        if (exceptionResolvable == null) {
            throw new IllegalArgumentException("UnifiedExceptionResolvable can not be null");
        }
        if (exceptionResolvable.getErrorCode() == ResultCodeEnumerable.DEFAULT.getSuccessCode()) {
            throw new IllegalArgumentException("UnifiedExceptionResolvable must be enum instance of fail-code");
        }
        return new ResultDTO<>(exceptionResolvable);
    }

    /**
     * 自定义统一响应体, 仅子类或包内可用
     *
     * @param errorCode
     * @param errorMessage
     * @param data
     * @return
     * @param <V>
     */
    protected static <V> ResultDTO<V> customize(int errorCode, String errorMessage, V data) {
        return new ResultDTO<>(errorCode, errorMessage, data);
    }

}
